from .core import Node
from . import builders


def load_builders():
    for name, mod in builders.__dict__.iteritems():
        if hasattr(mod, "register_builder"):
            mod.register_builder()


def create_nodelist(projfilename):
    rootnode = Node.create(projfilename)
    rootnode.scan_all()
    return rootnode.toposort()


def mark_changed(nodelist):
    """marks all changed and unchanged nodes in the nodelist; returns the 
    number of changed nodes. note: the nodelist must be topologically sorted"""
    unchanged = set()
    for node in nodelist:
        node.rebuild = False
        for child in node.children:
            if child not in unchanged:
                node.rebuild = True
                break
        if node.rebuild or (node.output is not None and 
        not os.path.exists(node.cache_filename)):
            node.clean()
            node.rebuild = True
        else:
            unchanged.add(node)
    return len(nodelist) - len(unchanged)


def build(nodelist, force = False):
    if not force:
        if mark_changed(nodelist) == 0:
            return
    for node in nodelist:
        node.build()


def clean(nodelist):
    for node in nodelist:
        node.clean()


MODE_BUILD = "build"
MODE_FORCE = "force"
MODE_CLEAN = "clean"


def start(projfilename, mode = MODE_BUILD):
    load_builders()
    nodelist = create_nodelist(projfilename)
    
    if mode == MODE_BUILD:
        build(nodelist, force = False)
    elif mode == MODE_FORCE:
        build(nodelist, force = True)
    elif mode == MODE_CLEAN:
        clean(nodelist)
    else:
        raise ValueError("Invalid mode: %r" % (mode,))



























